package com.lsp.helper;

import com.lsp.annotation.Autowired;
import com.lsp.util.ReflectionUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ArrayUtils;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Set;

/**
 * IOC容器
 * spring有两种容器：
 *              BeanFactory：采用延迟加载策略，在第一调用getBean时才真正装配对象
 *              ApplicationContext： 在应用启动时就把所有的对象一次性装配好
 */
public   class IocHelper {



    /**
     * 遍历bean容器所有的bean属性，为所有带@Atowire注解的属性注入实例
     */
    static {
        Map<Class<?>, Object> beanMap = BeanHelper.getBeanMap();
        if(MapUtils.isNotEmpty(beanMap)) {
           for(Map.Entry<Class<?>, Object> beanEntry : beanMap.entrySet()){
               Class<?> beanClass   = beanEntry.getKey();
               Object beanInstance  = beanEntry.getValue();
               Field[] declaredFields = beanClass.getDeclaredFields();
               if(ArrayUtils.isNotEmpty(declaredFields)){
                   for(Field beanField : declaredFields){
                       if(beanField.isAnnotationPresent(Autowired.class)){
                           Class<?> beanFieldClass  = beanField.getType();
                           beanFieldClass = findImplementClass(beanFieldClass);
                           Object beanFieldInstance  = beanMap.get(beanFieldClass);
                           if(beanFieldInstance != null){
                               ReflectionUtil.setField(beanInstance, beanField, beanFieldInstance);
                           }
                       }
                   }
               }

           }
        }

    }


    private static Class<?> findImplementClass(Class<?> interfaceClass) {
        Class<?> implementClass = interfaceClass;

        Set<Class<?>> classSetBySuper = ClassHelper.getClassSetBySuper(interfaceClass);
        if(CollectionUtils.isNotEmpty(classSetBySuper)){
            //获取第一个实现类
            implementClass = classSetBySuper.iterator().next();
        }
        return implementClass;
    }

}
